package com.zoe.onelink.auth.token.fallback;

import cn.hutool.crypto.symmetric.AES;
import com.zoe.onelink.auth.property.OnelinkAuthProperties;
import com.zoe.onelink.auth.token.processor.OnelinkTokenFallbackProvider;
import com.zoe.onelink.common.enumeration.ExceptionCodeEnum;
import com.zoe.onelink.common.exception.ApiException;
import com.zoe.onelink.util.StrUtil;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>标题: </p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2022</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: ruansheng
 * @date: 2022-08-19
 */
@Slf4j
public class DefaultOnelinkTokenFallbackProviderImpl implements OnelinkTokenFallbackProvider {

    private final AES aes;

    /**
     * 与门户约定的格式: userCode,staffNo,districtCode,orgCode
     */
    private static final String[] TOKEN_NAME_SEQ_ARR = {"userCode", "staffNo", "districtCode", "orgCode"};

    public DefaultOnelinkTokenFallbackProviderImpl(OnelinkAuthProperties onelinkAuthProperties) {
        this.aes = new AES(onelinkAuthProperties.getTokenSecretKey().getBytes(StandardCharsets.UTF_8));
    }

    @Override
    public Map<String, Object> onFallback(String onelinkToken) {
        if (log.isDebugEnabled()) {
            log.debug("[Token Fallback] Using Aes token decrypt,token is {}", onelinkToken);
        }
        String tokenInfoStr;
        try {
            tokenInfoStr = this.aes.decryptStr(onelinkToken);
        } catch (Exception e) {
            throw ApiException.createEx(e, ExceptionCodeEnum.TOKEN_SELF_PROTECT_FAILURE, "Token decrypt error");
        }
        if (StrUtil.isBlank(tokenInfoStr)) {
            throw ApiException.createEx(ExceptionCodeEnum.TOKEN_SELF_PROTECT_FAILURE, "Decrypted token not be blank");
        }
        String[] tokenInfoArr = tokenInfoStr.split(",");
        if (tokenInfoArr.length < TOKEN_NAME_SEQ_ARR.length) {
            String msg = StrUtil.format("Parsed token array length error,expected: {},actual: {}", TOKEN_NAME_SEQ_ARR.length, tokenInfoArr.length);
            throw ApiException.createEx(ExceptionCodeEnum.TOKEN_SELF_PROTECT_FAILURE, msg);
        }
        Map<String, Object> authInfo = new HashMap<>(TOKEN_NAME_SEQ_ARR.length);
        for (int i = 0; i < TOKEN_NAME_SEQ_ARR.length; i++) {
            authInfo.put(TOKEN_NAME_SEQ_ARR[i], tokenInfoArr[i]);

        }
        authInfo.put("operator", authInfo.get("staffNo"));
        return authInfo;
    }

}
